package com.eastfair.venuebooking.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.cloud.commons.lang.StringUtils;
import com.alibaba.fastjson.JSONObject;
//import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.eastfair.boot.request.PageParams;
import com.eastfair.boot.service.SuperServiceImpl;
import com.eastfair.constant.BusinessConstant;
import com.eastfair.core.base.R;
import com.eastfair.core.base.entity.SuperEntity;
import com.eastfair.core.context.ContextUtil;
import com.eastfair.core.exception.BizException;
import com.eastfair.core.utils.ConvertUtil;
import com.eastfair.database.mybatis.typehandler.TypeHandlerUtil;
import com.eastfair.pay.enums.PayStateEnum;
import com.eastfair.util.OrderUtil;
import com.eastfair.venuebooking.api.ExhibitionManageFeign;
import com.eastfair.venuebooking.dao.ExhibitionMapper;
import com.eastfair.venuebooking.dto.*;
import com.eastfair.venuebooking.entity.*;
import com.eastfair.venuebooking.enumeration.*;
import com.eastfair.venuebooking.enums.CustomerIdentityEnum;
import com.eastfair.venuebooking.enums.SegmentNameEnum;
import com.eastfair.venuebooking.exceptioncode.VenueBookingExceptionCode;
import com.eastfair.venuebooking.service.*;
import com.eastfair.venuebooking.vo.ContractManageVO;
import com.eastfair.venuebooking.vo.ExhibitionResponsibilityerVO;
import com.eastfair.venuebooking.vo.ExhibitionVO;
import com.eastfair.venueservice.dto.ExhibitionManageDTO;
import com.eastfair.venueservice.enumeration.ExhibitionManageExhibitionTypeEnum;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * <p>
 * 业务实现类
 * 展会
 * </p>
 *
 * @author linan
 * @date 2022-06-08
 */
@Slf4j
@Service
//@DS("#thread.tenant")
public class ExhibitionServiceImpl extends SuperServiceImpl<ExhibitionMapper, Exhibition> implements ExhibitionService {

    public static final String VALUE_ZERO = "0%";
    public static final String VALUE_ONE = "100%";
    public static final String ID = "id";
    public static final String DESCENDING = "descending";
    @Resource
    private ExhibitionSegmentService exhibitionSegmentService;
    @Resource
    private ExhibitionResponsibilityerService exhibitionResponsibilityerService;
    @Resource
    private SpaceService spaceService;
    @Resource
    private SpaceCategoryService spaceCategoryService;
    @Resource
    private ExhibitionTaskService exhibitionTaskService;
    @Resource
    private ExhibitionTaskOrgService exhibitionTaskOrgService;
    @Resource
    private ProjectExhibitionService projectExhibitionService;
    @Resource
    private ProjectService projectService;
    @Resource
    private QuotationDetailService quotationDetailService;
    @Resource
    private QuotationService quotationService;
    @Resource
    private ContractManageService contractManageService;
    @Resource
    private ExhibitionManageFeign exhibitionManageFeign;
    @Resource
    private CustomerMainService customerMainService;
    @Resource
    private ExhibitionBusinessOpportunityService exhibitionBusinessOpportunityService;

    @Resource
    private ExhibitionCustomerService exhibitionCustomerService;

    private final static String EXHIBITION_NUMBER_PREFIX = "EN";

    @Value("${outside.url}")
    private String outsideUrl;

    @Value("${outside.exhibition.url}")
    private String syncExhibitionUrl;

    /**
     * 处理逻辑删除相关处理
     *
     * @param modelList 实体
     * @return 是否成功
     */
    @Override
    protected R<Boolean> handlerRemoveByIdsOfLogic(Collection<Exhibition> modelList) {
        modelList.forEach(s -> {
            s.setIsDeleted(BusinessConstant.YES);
        });
        // TODO: 2021/10/29 这里需要操作其他业务，如清空角色等
        return R.successDef();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R addExhibition(ExhibitionDTO exhibitionSaveDTO) {
        // 判断是否存在重复，重复则无法成功提交表单
        dealQuery(exhibitionSaveDTO);
        // 展会时间校验
        checkExhibitionTime(exhibitionSaveDTO);
        // 商机校验
        checkBusinessOpportunity(exhibitionSaveDTO, Exhibition.builder().build());
        Exhibition exhibition = new Exhibition();
        BeanUtils.copyProperties(exhibitionSaveDTO, exhibition);
        // 默认未启用
        exhibition.setIsEnabled(BusinessConstant.NO);
        // 根据关联商机和关联报价书赋值初始状态
        dealDefaultState(exhibitionSaveDTO, exhibition);
        // 展会编号 不再自动生成
        // exhibition.setExhibitionNo(OrderUtil.getOrderNo(EXHIBITION_NUMBER_PREFIX));
        // 如果不是展览，撤展时间用展览结束时间
        if(Objects.nonNull(exhibitionSaveDTO.getExhibitionType()) && !exhibitionSaveDTO.getExhibitionType().eq(ExhibitionExhibitionTypeEnum.EXHIBITION)){
            exhibition.setDismantlingStartTime(exhibitionSaveDTO.getExhibitionStartTime());
            exhibition.setDismantlingEndTime(exhibitionSaveDTO.getExhibitionEndTime());
        }
        this.save(exhibition);
        Long id = exhibition.getId();
        // 插入商机
        List<Long> businessOpportunityIds = exhibitionSaveDTO.getBusinessOpportunityIds();
        if(CollectionUtils.isNotEmpty(businessOpportunityIds)){
            for (Long businessOpportunityId : businessOpportunityIds) {
               exhibitionBusinessOpportunityService.save(ExhibitionBusinessOpportunity.builder().exhibitionId(id).businessOpportunityId(businessOpportunityId).build());
            }
        }
        // 协助人员与主要负责人
        ExhibitionResponsibilityer exhibitionResponsibilityer = new ExhibitionResponsibilityer();
        exhibitionResponsibilityer.setExhibitionId(id);
        dealResponsibility(exhibitionSaveDTO, exhibitionResponsibilityer);
        if(CollectionUtil.isNotEmpty(exhibitionSaveDTO.getAssistingStaffList())){
            for (ExhibitionResponsibilityerSaveDTO exhibitionResponsibilityerSaveDTO : exhibitionSaveDTO.getAssistingStaffList()) {
                ExhibitionResponsibilityer assistingStaff = new ExhibitionResponsibilityer();
                assistingStaff.setExhibitionId(id);
                assistingStaff.setResponsibilityerRole(ResponsibilityerRoleEnum.ASSISTING_STAFF.getValue());
                assistingStaff.setUserId(exhibitionResponsibilityerSaveDTO.getUserId());
                assistingStaff.setUserName(exhibitionResponsibilityerSaveDTO.getUserName());
                assistingStaff.setOrgId(exhibitionResponsibilityerSaveDTO.getOrgId());
                assistingStaff.setOrgName(exhibitionResponsibilityerSaveDTO.getOrgName());
                exhibitionResponsibilityerService.save(assistingStaff);
            }
        }
        // 项目对应展会数量更新
        if(Objects.nonNull(exhibitionSaveDTO.getExhibitionProjectId())){
            ProjectExhibition projectExhibition = new ProjectExhibition();
            projectExhibition.setExhibitionId(id);
            projectExhibition.setExhibitionProjectId(exhibitionSaveDTO.getExhibitionProjectId());
            projectExhibitionService.save(projectExhibition);
            projectService.updateExhibitionSum(exhibitionSaveDTO.getExhibitionProjectId());
        }
        // 自动触发生成布展、展览、撤展的环节
        dealSegment(exhibition,id);
        // 保存报价书信息
        if(Objects.nonNull(exhibition.getQuotationId())){
            QuotationDTO quotation = new QuotationDTO();
            quotation.setId(exhibition.getQuotationId());
            quotation.setExhibitionId(id);
            quotationService.saveExhibitionQuotation(quotation);
        }
        // 主办 承办
        List<Long> sponsorIds = exhibitionSaveDTO.getSponsorIds();
        if(CollectionUtils.isNotEmpty(sponsorIds)){
            for (Long sponsorId : sponsorIds) {
                ExhibitionCustomerDTO dto =new ExhibitionCustomerDTO();
                dto.setExhibitionId(id);
                dto.setCustomerId(sponsorId);
                dto.setExhibitionName(exhibitionSaveDTO.getExhibitionName());
                dto.setCustomerIdentity(CustomerIdentityEnum.SPONSOR.getCode());
                dto.setBusinessType(ExhibitionCustomerBusinessTypeEnum.EXHIBITION);
                exhibitionCustomerService.saveExhibitionCustomer(dto);
            }
        }
        List<Long> undertakerIds = exhibitionSaveDTO.getUndertakerIds();
        if(CollectionUtils.isNotEmpty(undertakerIds)){
            for (Long undertakerId : undertakerIds) {
                ExhibitionCustomerDTO dto =new ExhibitionCustomerDTO();
                dto.setExhibitionId(id);
                dto.setCustomerId(undertakerId);
                dto.setExhibitionName(exhibitionSaveDTO.getExhibitionName());
                dto.setCustomerIdentity(CustomerIdentityEnum.UNDERTAKER.getCode());
                dto.setBusinessType(ExhibitionCustomerBusinessTypeEnum.EXHIBITION);
                exhibitionCustomerService.saveExhibitionCustomer(dto);
            }
        }
        return R.success(id);
    }

    private void checkBusinessOpportunity(ExhibitionDTO exhibitionSaveDTO, Exhibition oldExhibition) {
        if (Objects.nonNull(exhibitionSaveDTO.getBusinessOpportunityId())) {
            if (exhibitionBusinessOpportunityService.existExhibition(exhibitionSaveDTO.getBusinessOpportunityIds(),oldExhibition.getId())) {
                // 该商机已被其他展会使用
                log.error("商机id{}, {}", exhibitionSaveDTO.getBusinessOpportunityId(), VenueBookingExceptionCode.BUS_EXIST_EXHIBITION.getMsg());
                throw BizException.wrap(VenueBookingExceptionCode.BUS_EXIST_EXHIBITION);
            }
        }
    }

    /**
     * 处理主要负责人
     * @param exhibitionSaveDTO exhibitionSaveDTO
     * @param exhibitionResponsibilityer exhibitionResponsibilityer
     */
    private void dealResponsibility(ExhibitionDTO exhibitionSaveDTO, ExhibitionResponsibilityer exhibitionResponsibilityer) {
        if (exhibitionSaveDTO.getMainInCharge() != null) {
            exhibitionResponsibilityer.setResponsibilityerRole(ResponsibilityerRoleEnum.MAIN_IN_CHARGE.getValue());
            exhibitionResponsibilityer.setUserId(exhibitionSaveDTO.getMainInCharge().getUserId());
            exhibitionResponsibilityer.setUserName(exhibitionSaveDTO.getMainInCharge().getUserName());
            exhibitionResponsibilityer.setOrgId(exhibitionSaveDTO.getMainInCharge().getOrgId());
            exhibitionResponsibilityer.setOrgName(exhibitionSaveDTO.getMainInCharge().getOrgName());
            exhibitionResponsibilityerService.save(exhibitionResponsibilityer);
        }
    }

    @Override
    public R copyExhibition(ExhibitionDTO exhibitionSaveDTO) {
        // 判断是否存在重复，重复则无法成功提交表单
        dealQuery(exhibitionSaveDTO);
        checkExhibitionTime(exhibitionSaveDTO);
        Exhibition oldExhibition = this.getOne(new QueryWrapper<Exhibition>().lambda()
                .eq(Exhibition::getId,exhibitionSaveDTO.getId())
                .eq(Exhibition::getIsDeleted,BusinessConstant.NO));
        if(Objects.nonNull(oldExhibition)){
            // 拷贝实体类
            copyExhibitionEntity(exhibitionSaveDTO, oldExhibition);
            Long id = oldExhibition.getId();
            // 自动触发生成布展、展览、撤展的环节
            dealSegment(oldExhibition, id);
            // 项目对应展会数量更新
            if(Objects.nonNull(exhibitionSaveDTO.getExhibitionProjectId())){
                ProjectExhibition projectExhibition = new ProjectExhibition();
                projectExhibition.setExhibitionId(id);
                projectExhibition.setExhibitionProjectId(exhibitionSaveDTO.getExhibitionProjectId());
                projectExhibitionService.save(projectExhibition);
                projectService.updateExhibitionSum(exhibitionSaveDTO.getExhibitionProjectId());
            }
        }

        return R.success();
    }

    @Override
    public void syncExhibition(Exhibition exhibition) {
        ExhibitionManageDTO exhibitionManageDTO = new ExhibitionManageDTO();
        BeanUtils.copyProperties(exhibition, exhibitionManageDTO);
        exhibitionManageDTO.setId(null);
        exhibitionManageDTO.setVbExhibitionId(exhibition.getId());
        exhibitionManageDTO.setExhibitionType(null);
        if(Objects.nonNull(exhibition.getExhibitionMainType())){
            exhibitionManageDTO.setExhibitionType(ExhibitionManageExhibitionTypeEnum.get(exhibition.getExhibitionMainType().getCode()));
        }
        if(Objects.nonNull(exhibition.getExhibitionType())){
            exhibitionManageDTO.setVenueExhibitionType(exhibition.getExhibitionType());
        }
        // 查询主办名称
        ExhibitionCustomer exhibitionCustomer = exhibitionCustomerService.getOne(new QueryWrapper<ExhibitionCustomer>()
                .lambda()
                .eq(ExhibitionCustomer::getIsDeleted, BusinessConstant.NO)
                .eq(ExhibitionCustomer::getExhibitionId, exhibition.getId())
                .eq(ExhibitionCustomer::getCustomerIdentity, CustomerIdentityEnum.SPONSOR));
        if(Objects.nonNull(exhibitionCustomer)){
            CustomerMain customerMain = customerMainService.getById(exhibitionCustomer.getCustomerId());
            exhibitionManageDTO.setSponsorName(customerMain.getCustomerCnName());
        }
        R<Boolean> booleanR = exhibitionManageFeign.syncExhibition(exhibitionManageDTO);
        if (!booleanR.getIsSuccess()) {
            log.error("同步综合服务失败");
            throw BizException.wrap(booleanR.getCode(), booleanR.getMsg());
        }
    }

    @Override
    public Boolean syncExhibitionManage(ExhibitionDTO exhibitionDTO) {
        if(Objects.nonNull(exhibitionDTO) && Objects.nonNull(exhibitionDTO.getId())){
            LambdaUpdateWrapper<Exhibition> updateWrapper = new UpdateWrapper<Exhibition>().lambda().eq(SuperEntity::getId, exhibitionDTO.getId())
                    // 展会名称
                    .set(StringUtils.isNotBlank(exhibitionDTO.getExhibitionName()), Exhibition::getExhibitionName, exhibitionDTO.getExhibitionName())
                    // 主办单位
                    .set(StringUtils.isNotBlank(exhibitionDTO.getSponsorName()), Exhibition::getSponsorName, exhibitionDTO.getSponsorName())
                    // 行业属性
                    .set(Objects.nonNull(exhibitionDTO.getIndustry()), Exhibition::getIndustry, exhibitionDTO.getIndustry())
                    // 使用面积
                    .set(Objects.nonNull(exhibitionDTO.getReserveArea()), Exhibition::getReserveArea, exhibitionDTO.getReserveArea())
                    // 展会时间
                    .set(Objects.nonNull(exhibitionDTO.getArrangementStartTime()), Exhibition::getArrangementStartTime, exhibitionDTO.getArrangementStartTime())
                    .set(Objects.nonNull(exhibitionDTO.getArrangementEndTime()), Exhibition::getArrangementEndTime, exhibitionDTO.getArrangementEndTime())
                    .set(Objects.nonNull(exhibitionDTO.getExhibitionStartTime()), Exhibition::getExhibitionStartTime, exhibitionDTO.getExhibitionStartTime())
                    .set(Objects.nonNull(exhibitionDTO.getExhibitionEndTime()), Exhibition::getExhibitionEndTime, exhibitionDTO.getExhibitionEndTime())
                    .set(Objects.nonNull(exhibitionDTO.getDismantlingStartTime()), Exhibition::getDismantlingStartTime, exhibitionDTO.getDismantlingStartTime())
                    .set(Objects.nonNull(exhibitionDTO.getDismantlingEndTime()), Exhibition::getDismantlingEndTime, exhibitionDTO.getDismantlingEndTime());
            boolean result = this.update(updateWrapper);
            updateAutoSegment(this.getById(exhibitionDTO.getId()));
            return result;
        }
        return false;
    }

    @Override
    public Boolean updateConfirmExhibition(Long exhibitionId) {
        baseMapper.updateById(Exhibition.builder().id(exhibitionId).state(ExhibitionStateEnum.STATE_FOUR).isEnabled(BusinessConstant.YES).build());
        syncExhibition(this.getById(exhibitionId));
        return true;
    }

    /**
     * 拷贝实体类
     * @param exhibitionSaveDTO exhibitionSaveDTO
     * @param oldExhibition oldExhibition
     */
    private void copyExhibitionEntity(ExhibitionDTO exhibitionSaveDTO, Exhibition oldExhibition) {
        oldExhibition.setId(null);
        oldExhibition.setExhibitionName(exhibitionSaveDTO.getExhibitionName());
        oldExhibition.setArrangementStartTime(exhibitionSaveDTO.getArrangementStartTime());
        oldExhibition.setArrangementEndTime(exhibitionSaveDTO.getArrangementEndTime());
        oldExhibition.setExhibitionStartTime(exhibitionSaveDTO.getExhibitionStartTime());
        oldExhibition.setExhibitionEndTime(exhibitionSaveDTO.getExhibitionEndTime());
        oldExhibition.setDismantlingStartTime(exhibitionSaveDTO.getDismantlingStartTime());
        oldExhibition.setDismantlingEndTime(exhibitionSaveDTO.getDismantlingEndTime());
        oldExhibition.setCreatedBy(null);
        oldExhibition.setUpdatedBy(null);
        oldExhibition.setCreateTime(null);
        oldExhibition.setUpdateTime(null);
        oldExhibition.setBusinessOpportunityId(null);
        oldExhibition.setQuotationId(null);
        // 状态为无状态
        oldExhibition.setState(ExhibitionStateEnum.STATE_ONE);
        // 展会编号
        oldExhibition.setExhibitionNo(OrderUtil.getOrderNo(EXHIBITION_NUMBER_PREFIX));
        baseMapper.insert(oldExhibition);
    }

    /**
     * 判重查询
     * @param exhibitionSaveDTO exhibitionSaveDTO
     */
    private void dealQuery(ExhibitionDTO exhibitionSaveDTO) {
        QueryWrapper<Exhibition> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Exhibition::getExhibitionName,exhibitionSaveDTO.getExhibitionName())
                .eq(Exhibition::getIsDeleted, BusinessConstant.NO);
        int num = this.count(queryWrapper);
        if (num > 0) {
            //存在
            throw BizException.wrap(VenueBookingExceptionCode.EX_NAME_EXIST);
        }
        QueryWrapper<Exhibition> queryWrapper2 = new QueryWrapper<>();
        queryWrapper2.lambda().eq(Exhibition::getExhibitionNo,exhibitionSaveDTO.getExhibitionNo())
                .eq(Exhibition::getIsDeleted, BusinessConstant.NO);
        int num2 = this.count(queryWrapper2);
        if (num2 > 0) {
            //存在
            throw BizException.wrap(VenueBookingExceptionCode.EX_NO_EXIST);
        }
    }

    /**
     * 处理环节
     * @param oldExhibition
     * @param id
     */
    private void dealSegment(Exhibition oldExhibition, Long id) {
        // 布展环节
        ExhibitionSegment arrangementSegment = new ExhibitionSegment();
        arrangementSegment.setExhibitionId(id);
        arrangementSegment.setSegmentName(SegmentNameEnum.ARRANGEMENT_TIME.getDesc());
        arrangementSegment.setStartTime(oldExhibition.getArrangementStartTime());
        arrangementSegment.setEndTime(oldExhibition.getArrangementEndTime());
        arrangementSegment.setDeleteable(false);
        exhibitionSegmentService.save(arrangementSegment);
        // 展览环节
        ExhibitionSegment dismantlingSegment = new ExhibitionSegment();
        dismantlingSegment.setExhibitionId(id);
        dismantlingSegment.setSegmentName(SegmentNameEnum.EXHIBITION_TIME.getDesc());
        dismantlingSegment.setStartTime(oldExhibition.getExhibitionStartTime());
        dismantlingSegment.setEndTime(oldExhibition.getExhibitionEndTime());
        dismantlingSegment.setDeleteable(false);
        exhibitionSegmentService.save(dismantlingSegment);
        if (Objects.nonNull(oldExhibition.getExhibitionType()) && ExhibitionExhibitionTypeEnum.EXHIBITION.eq(oldExhibition.getExhibitionType())) {
            // 撤展环节
            ExhibitionSegment exhibitionSegment = new ExhibitionSegment();
            exhibitionSegment.setExhibitionId(id);
            exhibitionSegment.setSegmentName(SegmentNameEnum.DISMANTLING_TIME.getDesc());
            exhibitionSegment.setStartTime(oldExhibition.getDismantlingStartTime());
            exhibitionSegment.setEndTime(oldExhibition.getDismantlingEndTime());
            exhibitionSegment.setDeleteable(false);
            exhibitionSegmentService.save(exhibitionSegment);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public R updateExhibition(ExhibitionDTO exhibitionUpdateDTO) {
        Exhibition oldExhibition = this.getById(exhibitionUpdateDTO.getId());
        if (checkIsUpdateContract(exhibitionUpdateDTO)) {
            // 合同与报价书置为失效
            contractManageService.updateContractAndQuotationDisableByExhibitionId(exhibitionUpdateDTO.getId());
            // 展会需要回退到销售商机状态
            exhibitionUpdateDTO.setState(ExhibitionStateEnum.STATE_TWO);
        }
        checkExhibitionTime(exhibitionUpdateDTO);
        // 查询报价书
        QuotationDTO quotationDTO = new QuotationDTO();
        quotationDTO.setExhibitionId(exhibitionUpdateDTO.getId());
        List<Quotation> quotationList = quotationService.listQuotation(quotationDTO);
        if(quotationList.isEmpty()){
            exhibitionUpdateDTO.setQuotationId(null);
        }else {
            exhibitionUpdateDTO.setQuotationId(quotationList.get(0).getId());
        }
        // 判断是否存在重复，重复则无法成功提交表单
        QueryWrapper<Exhibition> existQueryWrapper = new QueryWrapper<>();
        existQueryWrapper.lambda().eq(Exhibition::getExhibitionName,exhibitionUpdateDTO.getExhibitionName())
                .eq(Exhibition::getIsDeleted, BusinessConstant.NO).ne(Exhibition::getId,exhibitionUpdateDTO.getId());
        int num = this.count(existQueryWrapper);
        if (num > 0) {
            //存在
            throw BizException.wrap(VenueBookingExceptionCode.EX_NAME_EXIST);
        }
        checkBusinessOpportunity(exhibitionUpdateDTO,oldExhibition);
        Exhibition exhibition = new Exhibition();
        BeanUtils.copyProperties(exhibitionUpdateDTO, exhibition);
        exhibition.setId(exhibitionUpdateDTO.getId());
        //  根据关联商机和关联报价书赋值更新状态
        if(ExhibitionStateEnum.STATE_ONE.eq(exhibition.getState()) || ExhibitionStateEnum.STATE_TWO.eq(exhibition.getState()) || ExhibitionStateEnum.STATE_THREE.eq(exhibition.getState()) ){
            dealDefaultState(exhibitionUpdateDTO, exhibition);
        }
        // 如果不是展览，撤展时间用展览结束时间
        if(Objects.nonNull(exhibitionUpdateDTO.getExhibitionType()) && !exhibitionUpdateDTO.getExhibitionType().eq(ExhibitionExhibitionTypeEnum.EXHIBITION)){
            exhibition.setDismantlingStartTime(exhibitionUpdateDTO.getExhibitionStartTime());
            exhibition.setDismantlingEndTime(exhibitionUpdateDTO.getExhibitionEndTime());
        }
        this.updateById(exhibition);
        // 清空绑定商机、报价书
        if(Objects.isNull(exhibitionUpdateDTO.getBusinessOpportunityId()) || Objects.isNull(exhibitionUpdateDTO.getQuotationId())){
            this.update(new UpdateWrapper<Exhibition>().lambda()
                    .eq(Exhibition::getId,exhibition.getId())
                    .set(Objects.isNull(exhibitionUpdateDTO.getBusinessOpportunityId()),Exhibition::getBusinessOpportunityId,null)
                    .set(Objects.isNull(exhibitionUpdateDTO.getQuotationId()),Exhibition::getQuotationId,null));
        }
        // 插入商机 先删除
        exhibitionBusinessOpportunityService.removeByExhibitionId(exhibitionUpdateDTO.getId());
        List<Long> businessOpportunityIds = exhibitionUpdateDTO.getBusinessOpportunityIds();
        if(CollectionUtils.isNotEmpty(businessOpportunityIds)){
            for (Long businessOpportunityId : businessOpportunityIds) {
                exhibitionBusinessOpportunityService.save(ExhibitionBusinessOpportunity.builder().exhibitionId(exhibition.getId()).businessOpportunityId(businessOpportunityId).build());
            }
        }
        // 更新负责人员 直接物理删除重新添加
        UpdateWrapper<ExhibitionResponsibilityer> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda().eq(ExhibitionResponsibilityer::getIsDeleted,BusinessConstant.NO).eq(ExhibitionResponsibilityer::getExhibitionId,exhibition.getId()).set(ExhibitionResponsibilityer::getIsDeleted,BusinessConstant.YES);
        exhibitionResponsibilityerService.update(updateWrapper);
        ExhibitionResponsibilityer exhibitionResponsibilityer = new ExhibitionResponsibilityer();
        exhibitionResponsibilityer.setExhibitionId(exhibition.getId());
        dealResponsibility(exhibitionUpdateDTO, exhibitionResponsibilityer);
        // 更新协助人员
        dealPeople(exhibitionUpdateDTO, exhibition);
        // 关联项目处理
        // 查询原项目展会关系
        dealProject(exhibitionUpdateDTO);
        // 自动触发更新布展、展览、撤展的环节
        updateAutoSegment(exhibition);
        // 主办 承办 先删除展会自建的
        exhibitionCustomerService.removeByExhibitionIdOfSelf(exhibition.getId());
        List<Long> sponsorIds = exhibitionUpdateDTO.getSponsorIds();
        if(CollectionUtils.isNotEmpty(sponsorIds)){
            for (Long sponsorId : sponsorIds) {
                ExhibitionCustomerDTO dto =new ExhibitionCustomerDTO();
                dto.setExhibitionId(exhibitionUpdateDTO.getId());
                dto.setCustomerId(sponsorId);
                dto.setExhibitionName(exhibitionUpdateDTO.getExhibitionName());
                dto.setCustomerIdentity(CustomerIdentityEnum.SPONSOR.getCode());
                dto.setBusinessType(ExhibitionCustomerBusinessTypeEnum.EXHIBITION);
                if(CollectionUtils.isEmpty(exhibitionCustomerService.listByExhibitionIdAndCustomerId(exhibition.getId(),sponsorId,CustomerIdentityEnum.SPONSOR.getCode())) ){
                    exhibitionCustomerService.saveExhibitionCustomer(dto);
                }
            }
        }
        List<Long> undertakerIds = exhibitionUpdateDTO.getUndertakerIds();
        if(CollectionUtils.isNotEmpty(undertakerIds)){
            for (Long undertakerId : undertakerIds) {
                ExhibitionCustomerDTO dto =new ExhibitionCustomerDTO();
                dto.setExhibitionId(exhibitionUpdateDTO.getId());
                dto.setCustomerId(undertakerId);
                dto.setExhibitionName(exhibitionUpdateDTO.getExhibitionName());
                dto.setCustomerIdentity(CustomerIdentityEnum.UNDERTAKER.getCode());
                dto.setBusinessType(ExhibitionCustomerBusinessTypeEnum.EXHIBITION);
                if(CollectionUtils.isEmpty(exhibitionCustomerService.listByExhibitionIdAndCustomerId(exhibition.getId(),undertakerId,CustomerIdentityEnum.UNDERTAKER.getCode())) ){
                    exhibitionCustomerService.saveExhibitionCustomer(dto);
                }
            }
        }
        // 如果展会状态是在活动确认之后 修改展会则同步展会
        Exhibition nowExhibition = this.getById(exhibition.getId());
        ExhibitionStateEnum state = nowExhibition.getState();
        if (!ExhibitionStateEnum.STATE_ONE.eq(state)
                && !ExhibitionStateEnum.STATE_TWO.eq(state)
                && !ExhibitionStateEnum.STATE_THREE.eq(state)) {
            syncExhibition(this.getById(exhibition.getId()));
        }
        return R.success();
    }

    /**
     * 校验展会时间
     * @param exhibitionDTO
     */
    private void checkExhibitionTime(ExhibitionDTO exhibitionDTO) {
        if (Objects.nonNull(exhibitionDTO.getArrangementEndTime()) && Objects.nonNull(exhibitionDTO.getExhibitionStartTime())
                && exhibitionDTO.getArrangementEndTime().compareTo(exhibitionDTO.getExhibitionStartTime()) >= 0) {
            throw BizException.wrap(VenueBookingExceptionCode.EX_CANT_ARRANGEMENT_MORE_TRAN_EXHIBITION);
        }
        if (Objects.nonNull(exhibitionDTO.getDismantlingStartTime()) && Objects.nonNull(exhibitionDTO.getExhibitionEndTime())
                && exhibitionDTO.getExhibitionEndTime().compareTo(exhibitionDTO.getDismantlingStartTime()) >= 0) {
            throw BizException.wrap(VenueBookingExceptionCode.EX_CANT_EXHIBITION_MORE_TRAN_DISMANTLING);
        }
    }

    /**
     * 处理展会默认状态
     * @param exhibitionUpdateDTO
     * @param exhibition
     */
    private void dealDefaultState(ExhibitionDTO exhibitionUpdateDTO, Exhibition exhibition) {
        if (Objects.nonNull(exhibitionUpdateDTO.getQuotationId())) {
            // 报价确认
            exhibition.setState(ExhibitionStateEnum.STATE_THREE);
        } else if (Objects.nonNull(exhibitionUpdateDTO.getBusinessOpportunityId()) || CollectionUtils.isNotEmpty(exhibitionUpdateDTO.getBusinessOpportunityIds())) {
            // 销售商机
            exhibition.setState(ExhibitionStateEnum.STATE_TWO);
        } else {
            // 无状态
            exhibition.setState(ExhibitionStateEnum.STATE_ONE);
        }
    }

    /**
     *
     * @param exhibitionUpdateDTO
     * @param exhibition
     */
    private void dealPeople(ExhibitionDTO exhibitionUpdateDTO, Exhibition exhibition) {
        if(CollectionUtil.isNotEmpty(exhibitionUpdateDTO.getAssistingStaffList())){
            for (ExhibitionResponsibilityerSaveDTO exhibitionResponsibilityerSaveDTO : exhibitionUpdateDTO.getAssistingStaffList()) {
                ExhibitionResponsibilityer assistingStaff = new ExhibitionResponsibilityer();
                assistingStaff.setExhibitionId(exhibition.getId());
                assistingStaff.setResponsibilityerRole(ResponsibilityerRoleEnum.ASSISTING_STAFF.getValue());
                assistingStaff.setUserId(exhibitionResponsibilityerSaveDTO.getUserId());
                assistingStaff.setUserName(exhibitionResponsibilityerSaveDTO.getUserName());
                assistingStaff.setOrgId(exhibitionResponsibilityerSaveDTO.getOrgId());
                assistingStaff.setOrgName(exhibitionResponsibilityerSaveDTO.getOrgName());
                exhibitionResponsibilityerService.save(assistingStaff);
            }
        }
    }

    /**
     * 查询原项目展会关系
     * @param exhibitionUpdateDTO
     */
    private void dealProject(ExhibitionDTO exhibitionUpdateDTO) {
        QueryWrapper<ProjectExhibition> projectExhibitionQueryWrapper = new QueryWrapper<>();
        projectExhibitionQueryWrapper.lambda().eq(ProjectExhibition::getExhibitionId, exhibitionUpdateDTO.getId()).eq(ProjectExhibition::getIsDeleted, BusinessConstant.NO);
        List<ProjectExhibition> projectExhibitionList = projectExhibitionService.list(projectExhibitionQueryWrapper);
        if (Objects.nonNull(exhibitionUpdateDTO.getExhibitionProjectId())) {
            if (CollectionUtils.isNotEmpty(projectExhibitionList)) {
                for (ProjectExhibition projectExhibition : projectExhibitionList) {
                    if (!projectExhibition.getExhibitionProjectId().equals(exhibitionUpdateDTO.getExhibitionProjectId())) {
                        // 先删除原有关系，再添加
                        projectExhibitionService.updateById(ProjectExhibition.builder().id(projectExhibition.getId()).isDeleted(BusinessConstant.YES).build());
                        ProjectExhibition newProjectExhibition = new ProjectExhibition();
                        newProjectExhibition.setExhibitionId(exhibitionUpdateDTO.getId());
                        newProjectExhibition.setExhibitionProjectId(exhibitionUpdateDTO.getExhibitionProjectId());
                        projectExhibitionService.save(newProjectExhibition);
                        projectService.updateExhibitionSum(projectExhibition.getExhibitionProjectId());
                        projectService.updateExhibitionSum(exhibitionUpdateDTO.getExhibitionProjectId());
                    }
                }
            } else {
                ProjectExhibition projectExhibition = new ProjectExhibition();
                projectExhibition.setExhibitionId(exhibitionUpdateDTO.getId());
                projectExhibition.setExhibitionProjectId(exhibitionUpdateDTO.getExhibitionProjectId());
                projectExhibitionService.save(projectExhibition);
                projectService.updateExhibitionSum(exhibitionUpdateDTO.getExhibitionProjectId());
            }
        } else {
            if (CollectionUtils.isNotEmpty(projectExhibitionList)) {
                for (ProjectExhibition projectExhibition : projectExhibitionList) {
                    // 删除原有关系
                    projectExhibitionService.updateById(ProjectExhibition.builder().id(projectExhibition.getId()).isDeleted(BusinessConstant.YES).build());
                    projectService.updateExhibitionSum(projectExhibition.getExhibitionProjectId());
                }
            }
        }
    }

    /**
     * 自动触发更新布展、展览、撤展的环节
     * @param exhibition exhibition
     */
    @Override
    public void updateAutoSegment(Exhibition exhibition) {
        // 自动触发更新布展、展览、撤展的环节
        QueryWrapper<ExhibitionSegment> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.lambda().eq(ExhibitionSegment::getExhibitionId, exhibition.getId()).eq(ExhibitionSegment::getIsDeleted, BusinessConstant.NO);
        for (ExhibitionSegment exhibitionSegment : exhibitionSegmentService.list(objectQueryWrapper)) {
            if (exhibitionSegment.getSegmentName().equals(SegmentNameEnum.ARRANGEMENT_TIME.getDesc())) {
                // 布展环节
                ExhibitionSegment updateEntity = new ExhibitionSegment();
                updateEntity.setId(exhibitionSegment.getId());
                updateEntity.setStartTime(exhibition.getArrangementStartTime());
                updateEntity.setEndTime(exhibition.getArrangementEndTime());
                exhibitionSegmentService.updateById(updateEntity);
            } else if (exhibitionSegment.getSegmentName().equals(SegmentNameEnum.EXHIBITION_TIME.getDesc())) {
                // 展览环节
                ExhibitionSegment updateEntity = new ExhibitionSegment();
                updateEntity.setId(exhibitionSegment.getId());
                updateEntity.setStartTime(exhibition.getExhibitionStartTime());
                updateEntity.setEndTime(exhibition.getExhibitionEndTime());
                exhibitionSegmentService.updateById(updateEntity);
            } else if (exhibitionSegment.getSegmentName().equals(SegmentNameEnum.DISMANTLING_TIME.getDesc())) {
                // 撤展环节
                ExhibitionSegment updateEntity = new ExhibitionSegment();
                updateEntity.setId(exhibitionSegment.getId());
                updateEntity.setStartTime(exhibition.getDismantlingStartTime());
                updateEntity.setEndTime(exhibition.getDismantlingEndTime());
                exhibitionSegmentService.updateById(updateEntity);
            }
        }
    }

    @Override
    public List<Map<String, Object>> selectExhibitionAndSpace(Long exhibitionId) {
        return baseMapper.selectExhibitionAndSpace(exhibitionId);
    }

    @Override
    public boolean updateBusinessOpportunityId(ExhibitionUpdateDTO updateDTO) {
        // 清空已绑定过商机的展会的商机
        UpdateWrapper<Exhibition> clearUpdateWrapper = new UpdateWrapper<>();
        clearUpdateWrapper.lambda()
                .eq(updateDTO.getBusinessOpportunityId() != null,
                        Exhibition::getBusinessOpportunityId, updateDTO.getBusinessOpportunityId())
                .set(Exhibition::getBusinessOpportunityId, null)
        ;
        update(clearUpdateWrapper);
        // 更新展会的商机
        Exhibition exhibition = this.getById(updateDTO.getId());
        UpdateWrapper<Exhibition> exhibitionUpdateWrapper = new UpdateWrapper<>();
        exhibitionUpdateWrapper
                .lambda()
                .eq(updateDTO.getId() != null, Exhibition::getId, updateDTO.getId())
                .set(updateDTO.getBusinessOpportunityId() != null,
                Exhibition::getBusinessOpportunityId, updateDTO.getBusinessOpportunityId())
                // 如果是无状态，则修改展会状态为销售商机
                .set(ExhibitionStateEnum.STATE_ONE.eq(exhibition.getState()),Exhibition::getState,ExhibitionStateEnum.STATE_TWO);
        return update(exhibitionUpdateWrapper);
    }

    @Override
    public Exhibition selectExhibitionByOpportunityId(Long opportunityId) {
        QueryWrapper<ExhibitionBusinessOpportunity> exhibitionQueryWrapper = new QueryWrapper<>();
        exhibitionQueryWrapper
                .lambda()
                .last("limit 1")
                .eq(ExhibitionBusinessOpportunity::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(ExhibitionBusinessOpportunity::getBusinessOpportunityId, opportunityId);
        ExhibitionBusinessOpportunity one = exhibitionBusinessOpportunityService.getOne(exhibitionQueryWrapper);
        if (Objects.nonNull(one)) {
            return getById(one.getExhibitionId());
        }
        return null;
    }

    @Override
    public Map<String, Object> getStatisticalItems(Long exhibitionId) {
        Map<String, Object> result = new HashMap<>(8);
        Exhibition exhibition = this.getById(exhibitionId);
        if (Objects.nonNull(exhibition)) {
            LocalDate now = LocalDate.now();
            // 布展时间
            LocalDate arrangementStartDate = exhibition.getArrangementStartTime().toLocalDate();
            // 开展时间
            LocalDate exhibitionStartDate = exhibition.getExhibitionStartTime().toLocalDate();
            // 撤展时间
            LocalDate dismantlingEndDate = exhibition.getDismantlingEndTime().toLocalDate();
            // 已启动天数 正数表示距启动，负数表示已启动
            result.put("started", arrangementStartDate.toEpochDay()-now.toEpochDay());
            // 距开展天数 正数表示距开展，负数表示已开展
            result.put("distanceStart", exhibitionStartDate.toEpochDay()-now.toEpochDay());
            // 项目进度
            long day1 = now.toEpochDay()-arrangementStartDate.toEpochDay()+1;
            long day2 = now.toEpochDay()-dismantlingEndDate.toEpochDay()+1;
            long day3 = dismantlingEndDate.toEpochDay()-arrangementStartDate.toEpochDay()+1;
            if(day1<=0){
                // 如果当前时间比展会布展时间小，则进度为0%
                result.put("projectProcess", VALUE_ZERO);
            } else if (day2 >= 0) {
                // 如果当前时间比展会撤展时间大，则进度为100%
                result.put("projectProcess", VALUE_ONE);
            }else {
                result.put("projectProcess", (Math.round(day1 *100.0/day3)+"%"));
            }

            // 场地预订情况
            List<Map<String, Object>> maps = this.selectExhibitionAndSpace(exhibitionId);
            AtomicInteger exhibitionHallNum = new AtomicInteger(0);
            AtomicInteger conferenceRoomNum = new AtomicInteger(0);
            AtomicInteger advertisingSpaceNum = new AtomicInteger(0);
            // todo 有则只有1条返回数据 ,嵌套逻辑待确认
            // 处理展厅数量
            dealSpaceNum(maps, exhibitionHallNum, conferenceRoomNum, advertisingSpaceNum);
            // 展厅
            result.put("exhibitionHallNum",exhibitionHallNum.get());
            // 会议室
            result.put("conferenceRoomNum",conferenceRoomNum.get());
            // 广告位
            result.put("advertisingSpaceNum",advertisingSpaceNum.get());
            // 合同金额
            PageParams<ContractManageQuery> pageParams = new PageParams<>();
            pageParams.setSize(999999);
            pageParams.setCurrent(1);
            ContractManageQuery contractManageQuery = new ContractManageQuery();
            contractManageQuery.setExhibitionId(exhibitionId);
            contractManageQuery.setIsDeleted(BusinessConstant.NO);
            contractManageQuery.setIsEnabled(BusinessConstant.YES);
            pageParams.setModel(contractManageQuery);
            IPage<ContractManageVO> contractManageVOIPage = contractManageService.listContractManageVOs(pageParams);
            List<ContractManageVO> records = contractManageVOIPage.getRecords();
            if(CollectionUtils.isNotEmpty(records)){
                // 总金额
                BigDecimal contractAmount = records.stream().map(ContractManageVO::getContractAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                result.put("contractAmount",contractAmount);
                // 已付款
                BigDecimal paid = records.stream().map(ContractManageVO::getContractReturndAmount).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
                result.put("paid", paid);
                // 占比
                BigDecimal bigDecimalDivide = paid.multiply(BigDecimal.valueOf(100L)).divide(contractAmount, 0, RoundingMode.HALF_DOWN);
                result.put("proportion", bigDecimalDivide + "%");
            }else {
                // 总金额
                result.put("contractAmount",0.00);
                // 已付款
                result.put("paid", 0.00);
                // 占比
                result.put("proportion", VALUE_ZERO);
            }

            // 任务执行
            QueryWrapper<ExhibitionTask> exhibitionTaskQueryWrapper = new QueryWrapper<>();
            exhibitionTaskQueryWrapper.lambda().eq(ExhibitionTask::getExhibitionId,exhibitionId).eq(ExhibitionTask::getIsDeleted,BusinessConstant.NO);
            List<ExhibitionTask> taskList = exhibitionTaskService.list(exhibitionTaskQueryWrapper);
            // 已执行任务数
            result.put("tasksExecutedNum", (int) taskList.stream().filter(e -> e.getFinishStatus().equals(ExhibitionTaskFinishStatusEnum.COMPLETED)
                    || e.getFinishStatus().equals(ExhibitionTaskFinishStatusEnum.HAVE_IN_HAND)).count());
            // 总任务数
            result.put("totalTasks", taskList.size());
        }
        return result;
    }

    @Override
    public Exhibition getByExternalExhibitionCode(String externalExhibitionCode) {
        log.info("getByExternalExhibitionCode - 外部展会ID获取展会, externalExhibitionCode={}", externalExhibitionCode);
        QueryWrapper<Exhibition> queryWrapper = new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(Exhibition::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Exhibition::getIsEnabled, BusinessConstant.ENABLE_YES)
                .eq(StrUtil.isNotBlank(externalExhibitionCode), Exhibition::getExternalExhibitionCode, externalExhibitionCode)
                ;
        List<Exhibition> list = list(queryWrapper);
        if(list == null || list.isEmpty()) {
            return null;
        }
        return list.get(0);
    }

    /**
     * 处理展会场地数量
     * @param maps
     * @param exhibitionHallNum
     * @param conferenceRoomNum
     * @param advertisingSpaceNum
     */
    private void dealSpaceNum(List<Map<String, Object>> maps, AtomicInteger exhibitionHallNum, AtomicInteger conferenceRoomNum, AtomicInteger advertisingSpaceNum) {
        for (Map<String, Object> map : maps) {
            map.forEach((a,spaceIds)->{
                for (String s : spaceIds.toString().split(BusinessConstant.COMMA)) {
                    Space space = spaceService.getById(Long.parseLong(s));
                    if (Objects.nonNull(space)) {
                        SpaceCategory spaceCategory = spaceCategoryService.getById(space.getSpaceCategoryId());
                        if (Objects.nonNull(spaceCategory)) {
                            if (SpaceCategorySpaceTypeEnum.EXHIBITION_HALL.eq(spaceCategory.getSpaceType())) {
                                exhibitionHallNum.addAndGet(1);
                            } else if (SpaceCategorySpaceTypeEnum.CONFERENCE_ROOM.eq(spaceCategory.getSpaceType())) {
                                conferenceRoomNum.addAndGet(1);
                            } else if (SpaceCategorySpaceTypeEnum.ADVERTISING_SPACE.eq(spaceCategory.getSpaceType())) {
                                advertisingSpaceNum.addAndGet(1);
                            }
                        }
                    }
                }
            });
        }
    }

    @Override
    public Map<String, Object> getCoordinationBookView(Long exhibitionId, LocalDate date, Exhibition exhibition, Map<String, Object> result) {
        // 展会名称
        result.put("exhibitionName",exhibition.getExhibitionName());
        // 客户名称
        result.put("customerName",exhibition.getCustomerName());
        QueryWrapper<ExhibitionResponsibilityer> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(ExhibitionResponsibilityer::getIsDeleted, BusinessConstant.NO).eq(ExhibitionResponsibilityer::getExhibitionId,exhibitionId);
        List<ExhibitionResponsibilityer> list = exhibitionResponsibilityerService.list(wrapper);
        // 主要负责人
        List<String> mainInCharge = list.stream().filter(e -> e.getResponsibilityerRole().equals(ResponsibilityerRoleEnum.MAIN_IN_CHARGE.getValue())).map(ExhibitionResponsibilityer::getUserName).collect(Collectors.toList());
        // 协助人员
        List<String> assistingStaff = list.stream().filter(e -> e.getResponsibilityerRole().equals(ResponsibilityerRoleEnum.ASSISTING_STAFF.getValue())).map(ExhibitionResponsibilityer::getUserName).collect(Collectors.toList());
        result.put("mainInCharge",mainInCharge);
        result.put("assistingStaff",assistingStaff);
        // 环节及任务
        QueryWrapper<ExhibitionSegment> exhibitionSegmentWrapper = new QueryWrapper<>();
        exhibitionSegmentWrapper.lambda().eq(ExhibitionSegment::getExhibitionId, exhibition.getId()).eq(ExhibitionSegment::getIsDeleted, BusinessConstant.NO).orderByAsc(ExhibitionSegment::getStartTime);
        List<Map<String, Object>> exhibitionSegmentList = new ArrayList<>();
        for (ExhibitionSegment exhibitionSegment : exhibitionSegmentService.list(exhibitionSegmentWrapper)) {
            QueryWrapper<ExhibitionTask> exhibitionTaskQueryWrapper = new QueryWrapper<>();
            exhibitionTaskQueryWrapper.lambda().eq(ExhibitionTask::getSegmentId,exhibitionSegment.getId()).eq(ExhibitionTask::getIsDeleted,BusinessConstant.NO);
            HashMap<String, Object> exhibitionSegmentMap = new HashMap<>(8);
            exhibitionSegmentMap.put("segmentName",exhibitionSegment.getSegmentName());
            // 获取部门、服务人员
            List<Map<String, Object>> taskList = new ArrayList<>();
            List<ExhibitionTask> exhibitionTaskList = exhibitionTaskService.list(exhibitionTaskQueryWrapper);
            for (ExhibitionTask exhibitionTask : exhibitionTaskList) {
                QueryWrapper<ExhibitionTaskOrg> exhibitionTaskOrgQueryWrapper = new QueryWrapper<>();
                exhibitionTaskOrgQueryWrapper.lambda()
                        .eq(ExhibitionTaskOrg::getTaskId,exhibitionTask.getId())
                        .eq(ExhibitionTaskOrg::getIsDeleted,BusinessConstant.NO);
                List<ExhibitionTaskOrg> exhibitionTaskOrgs = exhibitionTaskOrgService.list(exhibitionTaskOrgQueryWrapper);
                if(CollectionUtils.isNotEmpty(exhibitionTaskOrgs)){
                    for (ExhibitionTaskOrg exhibitionTaskOrg : exhibitionTaskOrgService.list(exhibitionTaskOrgQueryWrapper)) {
                        Map<String, Object> exhibitionTaskOrgMap = new HashMap<>(8);
                        // 任务名称
                        exhibitionTaskOrgMap.put("taskName",exhibitionTask.getTaskName());
                        // 开始时间
                        exhibitionTaskOrgMap.put("startTime",exhibitionTask.getStartTime().toLocalDate());
                        // 结束时间
                        exhibitionTaskOrgMap.put("endTime",exhibitionTask.getEndTime().toLocalDate());
                        // 服务部门
                        exhibitionTaskOrgMap.put("orgName",exhibitionTaskOrg.getOrgName());
                        // 负责人员
                        exhibitionTaskOrgMap.put("responsibleUserName",exhibitionTaskOrg.getResponsibleUserName());
                        taskList.add(exhibitionTaskOrgMap);
                    }
                }else {
                    Map<String, Object> exhibitionTaskOrgMap = new HashMap<>(8);
                    // 任务名称
                    exhibitionTaskOrgMap.put("taskName",exhibitionTask.getTaskName());
                    // 开始时间
                    exhibitionTaskOrgMap.put("startTime",exhibitionTask.getStartTime().toLocalDate());
                    // 结束时间
                    exhibitionTaskOrgMap.put("endTime",exhibitionTask.getEndTime().toLocalDate());
                    // 服务部门
                    exhibitionTaskOrgMap.put("orgName",Strings.EMPTY);
                    // 负责人员
                    exhibitionTaskOrgMap.put("responsibleUserName",Strings.EMPTY);
                    taskList.add(exhibitionTaskOrgMap);
                }
            }
            exhibitionSegmentMap.put("task",taskList);
            if(CollectionUtils.isNotEmpty(taskList)){
                exhibitionSegmentList.add(exhibitionSegmentMap);
            }else {
                Map<String, Object> exhibitionTaskOrgMap = new HashMap<>(8);
                // 任务名称
                exhibitionTaskOrgMap.put("taskName",Strings.EMPTY);
                // 开始时间
                exhibitionTaskOrgMap.put("startTime",Strings.EMPTY);
                // 结束时间
                exhibitionTaskOrgMap.put("endTime",Strings.EMPTY);
                // 服务部门
                exhibitionTaskOrgMap.put("orgName",Strings.EMPTY);
                // 负责人员
                exhibitionTaskOrgMap.put("responsibleUserName",Strings.EMPTY);
                taskList.add(exhibitionTaskOrgMap);
                exhibitionSegmentList.add(exhibitionSegmentMap);
            }
        }
        result.put("exhibitionSegment",exhibitionSegmentList);
        result.put("data",Objects.nonNull(date)?date:LocalDate.now());
        return result;
    }

    @Override
    public IPage<ExhibitionVO> queryExhibitionList(PageParams<ExhibitionQuery> params) {
        Page<ExhibitionVO> resultPage = params.buildPage();
        ExhibitionQuery exhibitionPageQuery = params.getModel();
        QueryWrapper<Exhibition> queryWrapper = new QueryWrapper<>();
        // 查询相关人员对应展会
        List<Long> exhibitionIds = null;
        if(Objects.nonNull(exhibitionPageQuery.getUserId())){
            QueryWrapper<ExhibitionResponsibilityer> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(ExhibitionResponsibilityer::getIsDeleted, BusinessConstant.NO).eq(ExhibitionResponsibilityer::getUserId,exhibitionPageQuery.getUserId());
            exhibitionIds = exhibitionResponsibilityerService.list(wrapper).stream().map(ExhibitionResponsibilityer::getExhibitionId).collect(Collectors.toList());
            exhibitionIds.add(0L);
        }
        LocalDateTime now = LocalDateTime.now();
        // 月初
        LocalDateTime thisMonth = LocalDateTime.of(now.getYear(), now.getMonth(), 1, 0, 0, 0, 0);
        LocalDateTime afterMonth = LocalDateTime.of(now.getYear(), now.getMonth(), 1, 0, 0, 0, 0).plusMonths(1L);
        // 查询项目对应展会id
        List<Long> exhibitionIdList = new ArrayList<>(16);
        if(Objects.nonNull(exhibitionPageQuery.getExhibitionProjectId())){
            QueryWrapper<ProjectExhibition> projectExhibitionWrapper = new QueryWrapper<>();
            projectExhibitionWrapper.lambda().eq(ProjectExhibition::getIsDeleted,BusinessConstant.NO).eq(ProjectExhibition::getExhibitionProjectId,exhibitionPageQuery.getExhibitionProjectId());
            exhibitionIdList = projectExhibitionService.list(projectExhibitionWrapper).stream().map(ProjectExhibition::getExhibitionId).collect(Collectors.toList());
            // 占位
            if(CollectionUtils.isEmpty(exhibitionIdList)){
                exhibitionIdList.add(0L);
            }
        }
        // 客户联系人模糊查询
        List<Long> customerIds = new ArrayList(16);
        if(StringUtils.isNotBlank(exhibitionPageQuery.getKeywords())){
            customerIds = baseMapper.getCustomerIdsByContactName(exhibitionPageQuery.getKeywords());
            // 占位
            if(CollectionUtils.isEmpty(customerIds)){
                customerIds.add(0L);
            }
        }
        List<Long> finalCustomerIds = customerIds;
        packageWrapper(exhibitionPageQuery, queryWrapper, exhibitionIds, thisMonth, afterMonth, exhibitionIdList, finalCustomerIds, params.getSort(), params.getOrder());
        Page<Exhibition> page = params.buildPage();
        page = this.page(page, queryWrapper);
        BeanUtils.copyProperties(page,resultPage);
        List<Exhibition> records = page.getRecords();
        List<ExhibitionVO> exhibitionVOs = new ArrayList<>();
        //  还需要赋值其他字段，不用ConvertUtil.convertList
        // todo 避免遍历中多次查询数据库，如果慢一次查多条
        for (Exhibition record : records) {
            ExhibitionVO exhibitionVO = dealExhibitionProject(record);
            // 客户联系人姓名与电话
            Map<String,String> nameAndMobile = baseMapper.getCutomerContactsNameAndMobile(record.getCustomerId());
            if(Objects.nonNull(nameAndMobile) && !nameAndMobile.isEmpty()){
                exhibitionVO.setTel(TypeHandlerUtil.decrypt(nameAndMobile.get("mobile")));
                exhibitionVO.setCutomerContactsName(nameAndMobile.get("name"));
            }

            // 查询展厅
            exhibitionVO.setSpaceNames(quotationDetailService.getSpaceNamesByExhibitionId(record.getId()));
            // 主要负责人 协助人员
            QueryWrapper<ExhibitionResponsibilityer> wrapper = new QueryWrapper<>();
            wrapper.lambda().eq(ExhibitionResponsibilityer::getIsDeleted, BusinessConstant.NO).eq(ExhibitionResponsibilityer::getExhibitionId,record.getId());
            List<ExhibitionResponsibilityer> exhibitionResponsibilityerList = exhibitionResponsibilityerService.list(wrapper);
            // 主要负责人
            List<ExhibitionResponsibilityer> collect = exhibitionResponsibilityerList.stream().filter(e -> e.getResponsibilityerRole().equals(ResponsibilityerRoleEnum.MAIN_IN_CHARGE.getValue())).map(e->e.setResponsibilityerRole(ResponsibilityerRoleEnum.MAIN_IN_CHARGE.getDesc())).collect(Collectors.toList());
            if(CollectionUtils.isNotEmpty(collect)){
                ExhibitionResponsibilityer exhibitionResponsibilityer = collect.get(0);
                ExhibitionResponsibilityerVO exhibitionResponsibilityerVO = new ExhibitionResponsibilityerVO();
                BeanUtils.copyProperties(exhibitionResponsibilityer,exhibitionResponsibilityerVO);
                exhibitionResponsibilityerVO.setId(exhibitionResponsibilityer.getId());
                exhibitionVO.setMainInCharge(exhibitionResponsibilityerVO);
            }

            // 协助人员
            List<ExhibitionResponsibilityer> assistingStaffList = exhibitionResponsibilityerList.stream().filter(e -> e.getResponsibilityerRole().equals(ResponsibilityerRoleEnum.ASSISTING_STAFF.getValue())).map(e->e.setResponsibilityerRole(ResponsibilityerRoleEnum.ASSISTING_STAFF.getDesc())).collect(Collectors.toList());
            exhibitionVO.setAssistingStaffList(ConvertUtil.convertList(assistingStaffList,ExhibitionResponsibilityerVO.class));
            // 展会商机
            List<Long> businessOpportunityIds = exhibitionBusinessOpportunityService.queryBusinessOpportunityIds(record.getId());
            exhibitionVO.setBusinessOpportunityIds(businessOpportunityIds);
            // 展会主办承办
            List<ExhibitionCustomer> exhibitionCustomerList = exhibitionCustomerService.list(new QueryWrapper<ExhibitionCustomer>()
                    .lambda()
                    .eq(ExhibitionCustomer::getIsDeleted, BusinessConstant.NO)
                    .eq(ExhibitionCustomer::getExhibitionId, record.getId()));
            Map<String, List<ExhibitionCustomer>> exhibitionCustomerMap = exhibitionCustomerList.stream().collect(Collectors.groupingBy(s -> s.getCustomerIdentity()));
            List<ExhibitionCustomer> sponsor = exhibitionCustomerMap.get(CustomerIdentityEnum.SPONSOR.getCode());
            List<ExhibitionCustomer> undertaker = exhibitionCustomerMap.get(CustomerIdentityEnum.UNDERTAKER.getCode());
            exhibitionVO.setSponsorIds(CollectionUtils.isNotEmpty(sponsor) ? sponsor.stream().map(ExhibitionCustomer::getCustomerId).collect(Collectors.toList()) : new ArrayList<>());
            exhibitionVO.setUndertakerIds(CollectionUtils.isNotEmpty(undertaker) ? undertaker.stream().map(ExhibitionCustomer::getCustomerId).collect(Collectors.toList()) : new ArrayList<>());
            exhibitionVO.setSponsorIdsCantCancel(CollectionUtils.isNotEmpty(sponsor) ? sponsor.stream().filter(e->!e.getBusinessType().eq(ExhibitionCustomerBusinessTypeEnum.EXHIBITION)).map(ExhibitionCustomer::getCustomerId).collect(Collectors.toList()) : new ArrayList<>());
            exhibitionVO.setUndertakerIdsCantCancel(CollectionUtils.isNotEmpty(undertaker) ? undertaker.stream().filter(e->!e.getBusinessType().eq(ExhibitionCustomerBusinessTypeEnum.EXHIBITION)).map(ExhibitionCustomer::getCustomerId).collect(Collectors.toList()) : new ArrayList<>());
            // 只有展会有撤展时间
            if (!ExhibitionExhibitionTypeEnum.EXHIBITION.eq(exhibitionVO.getExhibitionType())) {
                exhibitionVO.setDismantlingStartTime(null);
                exhibitionVO.setDismantlingEndTime(null);
            }
            exhibitionVOs.add(exhibitionVO);
        }
        resultPage.setRecords(exhibitionVOs);
        return resultPage;
    }

    /**
     * 封装wrapper
     * @param exhibitionPageQuery
     * @param queryWrapper
     * @param exhibitionIds
     * @param thisMonth
     * @param afterMonth
     * @param exhibitionIdList
     * @param finalCustomerIds
     * @param sort
     * @param order
     */
    private void packageWrapper(ExhibitionQuery exhibitionPageQuery, QueryWrapper<Exhibition> queryWrapper, List<Long> exhibitionIds, LocalDateTime thisMonth, LocalDateTime afterMonth, List<Long> exhibitionIdList, List<Long> finalCustomerIds, String sort, String order) {
        queryWrapper.lambda().eq(Exhibition::getIsDeleted, BusinessConstant.NO)
                // 客户id
                .eq(Objects.nonNull(exhibitionPageQuery.getCustomerId()),Exhibition::getCustomerId, exhibitionPageQuery.getCustomerId())
                // 展会状态
                .eq(Objects.nonNull(exhibitionPageQuery.getId()),Exhibition::getId, exhibitionPageQuery.getId())
                // 展会状态
                .eq(Strings.isNotBlank(exhibitionPageQuery.getState()),Exhibition::getState, exhibitionPageQuery.getState())
                // 布展时间
                .and(Objects.nonNull(exhibitionPageQuery.getArrangementStartTime()) && Objects.nonNull(exhibitionPageQuery.getArrangementEndTime())
                        ,e->e.or(f->f.le(Exhibition::getArrangementStartTime, exhibitionPageQuery.getArrangementStartTime()).ge(Exhibition::getArrangementEndTime, exhibitionPageQuery.getArrangementStartTime()))
                                .or(f->f.le(Exhibition::getArrangementStartTime, exhibitionPageQuery.getArrangementEndTime()).ge(Exhibition::getArrangementEndTime, exhibitionPageQuery.getArrangementEndTime()))
                )
                // 撤展时间
                .and(Objects.nonNull(exhibitionPageQuery.getDismantlingStartTime()) && Objects.nonNull(exhibitionPageQuery.getDismantlingEndTime())
                        ,e->e.or(f->f.le(Exhibition::getDismantlingStartTime, exhibitionPageQuery.getDismantlingStartTime()).ge(Exhibition::getDismantlingEndTime, exhibitionPageQuery.getDismantlingStartTime()))
                                .or(f->f.le(Exhibition::getDismantlingStartTime, exhibitionPageQuery.getDismantlingEndTime()).ge(Exhibition::getDismantlingEndTime, exhibitionPageQuery.getDismantlingEndTime()))
                )
                // 展览时间
                .and(Objects.nonNull(exhibitionPageQuery.getExhibitionStartTime()) && Objects.nonNull(exhibitionPageQuery.getExhibitionEndTime())
                        ,e->e.or(f->f.le(Exhibition::getExhibitionStartTime, exhibitionPageQuery.getExhibitionStartTime()).ge(Exhibition::getExhibitionEndTime, exhibitionPageQuery.getExhibitionStartTime()))
                                .or(f->f.le(Exhibition::getExhibitionStartTime, exhibitionPageQuery.getExhibitionEndTime()).ge(Exhibition::getExhibitionEndTime, exhibitionPageQuery.getExhibitionEndTime()))
                )
                .eq(Objects.nonNull(exhibitionPageQuery.getCreatedBy()), Exhibition::getCreatedBy, exhibitionPageQuery.getCreatedBy())
                // 相关用户id非空时查询，且避免传入的空集合，查询集合存一条默认值0的数据
                .in(Objects.nonNull(exhibitionPageQuery.getUserId()), Exhibition::getId, exhibitionIds)
                // 项目对应展会
                .in(CollectionUtils.isNotEmpty(exhibitionIdList), Exhibition::getId, exhibitionIdList)
                .like(Objects.nonNull(exhibitionPageQuery.getExhibitionName()), Exhibition::getExhibitionName, exhibitionPageQuery.getExhibitionName())
                // 展会名称、客户名称、联系人关键词检索
                .and(StringUtils.isNotBlank(exhibitionPageQuery.getKeywords()),
                        e->e.like(Exhibition::getExhibitionName, exhibitionPageQuery.getKeywords())
                                .or().like(Exhibition::getCustomerName, exhibitionPageQuery.getKeywords())
                                .or().in(Exhibition::getCustomerId, finalCustomerIds))
                // 是否当月（布展开始时间当月？撤展结束时间当月？布展开始小于当月且撤展结束大于当月？）
                .and(Objects.nonNull(exhibitionPageQuery.getIsThisMonth()) && exhibitionPageQuery.getIsThisMonth().equals(BusinessConstant.YES),
                        e-> e.or(f->f.ge(Exhibition::getArrangementStartTime, thisMonth).lt(Exhibition::getArrangementStartTime, afterMonth))
                                .or(f->f.ge(Exhibition::getDismantlingEndTime, thisMonth).lt(Exhibition::getDismantlingEndTime, afterMonth))
                                .or(f->f.lt(Exhibition::getArrangementStartTime, thisMonth).ge(Exhibition::getDismantlingEndTime, afterMonth)));
        queryWrapper.orderByAsc("abs(TIMEDIFF(now(),arrangement_start_time))");
    }

    private ExhibitionVO dealExhibitionProject(Exhibition record) {
        ExhibitionVO exhibitionVO = new ExhibitionVO();
        BeanUtils.copyProperties(record,exhibitionVO);
        exhibitionVO.setId(record.getId());
        // 处理项目id、项目名称
        QueryWrapper<ProjectExhibition> projectExhibitionQueryWrapper = new QueryWrapper<>();
        projectExhibitionQueryWrapper.lambda()
                .eq(ProjectExhibition::getExhibitionId, record.getId())
                .eq(ProjectExhibition::getIsDeleted,BusinessConstant.NO)
                .eq(ProjectExhibition::getIsEnabled,BusinessConstant.YES);
        List<ProjectExhibition> list = projectExhibitionService.list(projectExhibitionQueryWrapper);
        for (ProjectExhibition projectExhibition : list) {
            Project project = projectService.getById(projectExhibition.getExhibitionProjectId());
            if(Objects.nonNull(project)){
                exhibitionVO.setExhibitionProjectId(project.getId());
                exhibitionVO.setProjectName(project.getProjectName());
            }
        }
        return exhibitionVO;
    }

    @Override
    public Boolean updateExhibitionState(Long exhibitionId, ExhibitionStateEnum state) {
        Exhibition exhibition = new Exhibition();
        exhibition.setId(exhibitionId);
        exhibition.setState(state);
        return this.updateById(exhibition);
    }

    @Override
    public IPage<ExhibitionVO> queryRecentExhibitionList(PageParams<ExhibitionQuery> params) {
        QueryWrapper<Exhibition> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Exhibition::getIsDeleted, BusinessConstant.NO)
                // 撤展时间 未撤展
                .ge(Exhibition::getDismantlingEndTime, LocalDate.now().atStartOfDay())
                // 根据布展开始时间倒序
                .orderByAsc(Exhibition::getArrangementStartTime);
        Page<Exhibition> page = new Page<>(params.getCurrent() , params.getSize());
        page = this.page(page, queryWrapper);
        Page<ExhibitionVO> resultPage = params.buildPage();
        BeanUtils.copyProperties(page,resultPage);
        List<Exhibition> records = page.getRecords();
        List<ExhibitionVO> exhibitions = new ArrayList<>();
        //  还需要赋值其他字段，不用ConvertUtil.convertList
        for (Exhibition record : records) {
            ExhibitionVO exhibitionVO = dealExhibitionProject(record);
            // 查询展厅
            exhibitionVO.setSpaceNames(quotationDetailService.getSpaceNamesByExhibitionId(record.getId()));
            exhibitions.add(exhibitionVO);
        }
        resultPage.setRecords(exhibitions);
        return resultPage;
    }

    @Override
    public Map<String, Object> getExhibitionCalendar(String keywords) {
        Map<String, Object> result = new HashMap<>(8);
        //查询展馆 用报价书查和展会关系查
        QueryWrapper<Quotation> quotationQueryWrapper = new QueryWrapper<>();
        quotationQueryWrapper.lambda().eq(Quotation::getIsDeleted,BusinessConstant.NO);
        List<Quotation> list = quotationService.list(quotationQueryWrapper);
        List<Long> quotations = list.stream().map(Quotation::getId).distinct().collect(Collectors.toList());
        quotations.add(0L);

        QueryWrapper<QuotationDetail> quotationDetailQueryWrapper = new QueryWrapper<>();
        quotationDetailQueryWrapper.lambda().eq(QuotationDetail::getIsDeleted,BusinessConstant.NO).in(QuotationDetail::getQuotitionId,quotations);
        List<QuotationDetail> quotationDetails = quotationDetailService.list(quotationDetailQueryWrapper);
        Map<Long, String> collect = quotationDetails.stream().filter(e -> e.getIsDeleted().equals(BusinessConstant.NO) && StringUtils.isNotBlank(e.getSpaceName())).collect(Collectors.toMap(QuotationDetail::getSpaceId, QuotationDetail::getSpaceName, (k1, k2) -> k2));

        // 展厅展会关系
        Map<Object, Object> exhibitionAndSpace = this.selectExhibitionAndSpace(null).stream().collect(Collectors.toMap(e -> e.get("exhibition_id"), e -> e.get("space_id"), (k1, k2) -> k2));

        // 展厅对象集合
        List<Map<String, Object>> resources = new ArrayList<>(8);
        collect.forEach((a,b)->{
            Map<String, Object> map = new HashMap<>(2);
            map.put("id",a);
            map.put("title",b);
            resources.add(map);
        });

        // 日历事件 展会
        List<Map<String, Object>> eventList = new ArrayList<>(8);

        List<Exhibition> exhibitions = this.list(new QueryWrapper<Exhibition>().lambda().eq(Exhibition::getIsDeleted,BusinessConstant.NO)).stream().filter(e -> e.getIsDeleted().equals(BusinessConstant.NO)).collect(Collectors.toList());
        for (Exhibition exhibition : exhibitions) {
            Map<String, Object> map = new HashMap<>(8);
            map.put("id",exhibition.getId());
            map.put("title",exhibition.getExhibitionName());
            map.put("arrangementStartTime",exhibition.getArrangementStartTime());
            map.put("arrangementEndTime",exhibition.getArrangementEndTime());
            map.put("dismantlingStartTime",exhibition.getDismantlingStartTime());
            map.put("dismantlingEndTime",exhibition.getDismantlingEndTime());
            map.put("exhibitionStartTime",exhibition.getExhibitionStartTime());
            map.put("exhibitionEndTime",exhibition.getExhibitionEndTime());
            map.put("exhibitionType",exhibition.getExhibitionType().getDesc());
            ExhibitionStateEnum exhibitionStateEnum = exhibition.getState();
            map.put("state", exhibition.getState().getDesc());
            if(Objects.nonNull(exhibitionStateEnum)){
                map.put("stateName", exhibitionStateEnum.getDesc());
            }
            Set<Long> longs = new HashSet<>();
            Object o = exhibitionAndSpace.get(Long.parseLong(exhibition.getId().toString()));
            if(Objects.nonNull(o)){
                for (String s : o.toString().split(BusinessConstant.COMMA)) {
                    longs.add(Long.parseLong(s));
                }
            }
            map.put("spaceIds",longs);
            map.put("entity",exhibition);
            if(StringUtils.isBlank(keywords) || exhibition.getExhibitionName().toLowerCase().contains(keywords.toLowerCase())){
                eventList.add(map);
            }
        }
        result.put("resources",resources);
        result.put("eventList",eventList);
        // 所有展会状态
        result.put("stateNames", Arrays.stream(ExhibitionStateEnum.values()).map(ExhibitionStateEnum::getDesc).collect(Collectors.toList()));
        // 所有展会类型
        result.put("exhibitionTypes", Arrays.stream(ExhibitionExhibitionTypeEnum.values()).map(ExhibitionExhibitionTypeEnum::getDesc).collect(Collectors.toList()));
        return result;
    }

    @Override
    public void dealPaidResult(Long exhibitionId) {
        if(contractManageService.list(new QueryWrapper<ContractManage>().lambda()
                        .eq(ContractManage::getExhibitionId,exhibitionId).eq(ContractManage::getIsDeleted,BusinessConstant.NO)
                        .eq(ContractManage::getIsEnabled,BusinessConstant.YES))
                .stream().allMatch(e->e.getContractPayState().equals(PayStateEnum.PAYED.getCode()))) {
            log.info("展会id：{}，合同已全部付款",exhibitionId);
            Exhibition exhibition = this.getById(exhibitionId);
            if(Objects.nonNull(exhibition)){
                exhibition.setState(ExhibitionStateEnum.STATE_SIX);
                this.updateById(exhibition);
            }
        }
    }

    @Override
    public long countExhibitionByCustomerId(Long customerId) {

        QueryWrapper<Exhibition> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Exhibition::getIsDeleted, BusinessConstant.DELETE_NO)
                .eq(Exhibition::getCustomerId, customerId);
        return count(queryWrapper);
    }

    @Override
    public boolean existExhibition(ExhibitionQuery query) {
        log.info("listExhibitionByCustomerIds - 查询展会列表, query={}", query);

        QueryWrapper<Exhibition> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(Exhibition::getIsDeleted, BusinessConstant.DELETE_NO)
                .in(query.getCustomerIdList() != null && !query.getCustomerIdList().isEmpty(),
                        Exhibition::getCustomerId, query.getCustomerIdList())
                .in(query.getBusinessOpportunityIdList() != null && !query.getBusinessOpportunityIdList().isEmpty(),
                        Exhibition::getBusinessOpportunityId, query.getBusinessOpportunityIdList())
        ;
        return count(queryWrapper) > 0;
    }

    @Override
    public boolean existExhibitionByCustomerIds(List<Long> customerId) {
        ExhibitionQuery query = new ExhibitionQuery();
        query.setCustomerIdList(customerId);
        return existExhibition(query);
    }

    @Override
    public boolean existExhibitionByBusinessOpportunityIds(List<Long> businessOpportunityIds) {
        return exhibitionBusinessOpportunityService.existExhibition(businessOpportunityIds, null);
    }

    @Override
    public boolean checkIsUpdateContract(ExhibitionDTO updateDTO) {
        Exhibition oldExhibition = this.getById(updateDTO.getId());
        if (ExhibitionStateEnum.STATE_ONE.eq(oldExhibition.getState()) || ExhibitionStateEnum.STATE_TWO.eq(oldExhibition.getState())) {
            return false;
        }
        boolean updateExhibitionName = !updateDTO.getExhibitionName().equals(oldExhibition.getExhibitionName());
        boolean updateArrangementStartTime = !updateDTO.getArrangementStartTime().isEqual(oldExhibition.getArrangementStartTime());
        boolean updateArrangementEndTime = !updateDTO.getArrangementEndTime().isEqual(oldExhibition.getArrangementEndTime());
        boolean updateExhibitionStartTime = !updateDTO.getExhibitionStartTime().isEqual(oldExhibition.getExhibitionStartTime());
        boolean updateExhibitionEndTime = !updateDTO.getExhibitionEndTime().isEqual(oldExhibition.getExhibitionEndTime());
        boolean updateDismantlingStartTime = !updateDTO.getDismantlingStartTime().isEqual(oldExhibition.getDismantlingStartTime());
        boolean updateDismantlingEndTime = !updateDTO.getDismantlingEndTime().isEqual(oldExhibition.getDismantlingEndTime());
        return updateExhibitionName
                || updateArrangementStartTime || updateArrangementEndTime
                || updateExhibitionStartTime || updateExhibitionEndTime
                || updateDismantlingStartTime || updateDismantlingEndTime;
    }

    @Override
    public List<ExhibitionVO> queryNeedSyncExhibition() {
        List<Exhibition> list = list(new QueryWrapper<Exhibition>().lambda().eq(Exhibition::getSyncState, BusinessConstant.NO));
        List<ExhibitionVO> exhibitionVOS = new ArrayList<>(8);
        for (Exhibition exhibition : list) {
            ExhibitionVO exhibitionVO = BeanUtil.copyProperties(exhibition, ExhibitionVO.class);
            if(Objects.nonNull(exhibitionVO.getCustomerId())){
                CustomerMain customerMain = customerMainService.getById(exhibitionVO.getCustomerId());
                if(Objects.nonNull(customerMain)){
                    exhibitionVO.setUscc(customerMain.getUscc());
                }
            }
            exhibitionVOS.add(exhibitionVO);
        }
        return exhibitionVOS;
    }

    @Override
    public Long saveForVenueBook(VenueBookAudit venueBookAudit, Long customerMainId, String customerMainName, Long contactId, String contactName) {
        log.info("saveForVenueBook - 场馆预定审核通过生成展会, venueBookAudit={}, customerMainId={}, customerMainName={}, contactId={}, contactName={}",
                venueBookAudit, customerMainId, customerMainName, contactId, contactName);
        if (StrUtil.isNotBlank(venueBookAudit.getExternalExhibitionCode())) {
            Exhibition exhibition = getByExternalExhibitionCode(venueBookAudit.getExternalExhibitionCode());
            if (exhibition != null) {
                throw BizException.wrap(1001, "外部展会标识已存在，不可重复创建");
            }
        }
        // 保存展会
        ExhibitionDTO exhibitionDTO = new ExhibitionDTO();
        exhibitionDTO.setExternalExhibitionCode(venueBookAudit.getExternalExhibitionCode());
        exhibitionDTO.setExhibitionName(venueBookAudit.getExhibitionName());
        exhibitionDTO.setExhibitionNo(venueBookAudit.getExhibitionNo());
        exhibitionDTO.setExhibitionShortName(venueBookAudit.getExhibitionShortName());
        if (StrUtil.isNotBlank(venueBookAudit.getExhibitionType())) {
            ExhibitionExhibitionTypeEnum exhibitionType = ExhibitionExhibitionTypeEnum.get(venueBookAudit.getExhibitionType());
            exhibitionDTO.setExhibitionType(exhibitionType);
        }
        exhibitionDTO.setExhibitionEnName(venueBookAudit.getExhibitionEnName());
        exhibitionDTO.setRemark(venueBookAudit.getRemark());
        if (StrUtil.isNotBlank(venueBookAudit.getIndustry())) {
            ExhibitionIndustryEnum industry = ExhibitionIndustryEnum.get(venueBookAudit.getIndustry());
            exhibitionDTO.setIndustry(industry);
        }
        exhibitionDTO.setUndertakerName(venueBookAudit.getUndertakerName());
        exhibitionDTO.setLogoUrl(venueBookAudit.getLogoUrl());
        exhibitionDTO.setExhibitionStartTime(venueBookAudit.getExhibitionStartTime());
        exhibitionDTO.setExhibitionEndTime(venueBookAudit.getExhibitionEndTime());
        exhibitionDTO.setArrangementStartTime(venueBookAudit.getArrangementStartTime());
        exhibitionDTO.setArrangementEndTime(venueBookAudit.getArrangementEndTime());
        exhibitionDTO.setDismantlingStartTime(venueBookAudit.getDismantlingStartTime());
        exhibitionDTO.setDismantlingEndTime(venueBookAudit.getDismantlingEndTime());
        exhibitionDTO.setSponsorName(venueBookAudit.getSponsorName());
        exhibitionDTO.setExhibitionWebsite(venueBookAudit.getExhibitionWebsite());
        exhibitionDTO.setCustomerId(customerMainId);
        exhibitionDTO.setCustomerName(customerMainName);
        exhibitionDTO.setCutomerContactsId(contactId);
        exhibitionDTO.setCutomerContactsName(contactName);
        exhibitionDTO.setExhibitionMainType(ExhibitionExhibitionMainTypeEnum.SELF_EXHIBITION);
        R result = addExhibition(exhibitionDTO);
        return (Long) result.getData();
    }

    @Override
    public Object checkSamePeriodExhibition(ExhibitionDTO exhibitionDTO) {
        List<Exhibition> list = list(new QueryWrapper<Exhibition>().lambda().eq(Exhibition::getIsDeleted, BusinessConstant.NO)
                .ne(Objects.nonNull(exhibitionDTO.getId()),Exhibition::getId,exhibitionDTO.getId())
                .and(Objects.nonNull(exhibitionDTO.getArrangementStartTime()) && Objects.nonNull(exhibitionDTO.getDismantlingEndTime())
                , e-> e.or(f->f.ge(Exhibition::getArrangementStartTime, exhibitionDTO.getArrangementStartTime()).lt(Exhibition::getArrangementStartTime, exhibitionDTO.getDismantlingEndTime()))
                        .or(f->f.ge(Exhibition::getDismantlingEndTime, exhibitionDTO.getArrangementStartTime()).lt(Exhibition::getDismantlingEndTime, exhibitionDTO.getDismantlingEndTime()))
                        .or(f->f.lt(Exhibition::getArrangementStartTime, exhibitionDTO.getArrangementStartTime()).ge(Exhibition::getDismantlingEndTime, exhibitionDTO.getDismantlingEndTime())))
        );
        if (CollectionUtils.isNotEmpty(list)) {
            return String.format("所预订的展会与%s时间冲突，请合理安排时间！", list.get(0).getExhibitionName());
        }
        return true;
    }

    @Override
    public void syncExhibitionToOutside(Exhibition exhibition) {
//        String httpUrl ="http://60.205.157.219:9003/v1/public/exhibition/save";
        String httpUrl = outsideUrl + syncExhibitionUrl;
        ToOutsideExhibition toOutsideExhibition = new ToOutsideExhibition();
        toOutsideExhibition.setBizId(exhibition.getId().toString());
        toOutsideExhibition.setNameCn(exhibition.getExhibitionName());
        toOutsideExhibition.setIntroCn(exhibition.getRemark());
        toOutsideExhibition.setOrganizerCn(exhibition.getSponsorName());
        toOutsideExhibition.setContactCn(exhibition.getCutomerContactsName());
        toOutsideExhibition.setWebsite(exhibition.getExhibitionWebsite());
        toOutsideExhibition.setSource("其他");
        toOutsideExhibition.setPicUrl(exhibition.getLogoUrl());
        String httpAttr = JSONObject.toJSONString(toOutsideExhibition);;
        try {
            HttpResponse miceHttp = HttpRequest
                    .post(httpUrl)
                    .contentType("application/json")
                    .body(httpAttr)
                    .timeout(10000)
                    .execute();
            if (!miceHttp.isOk()) {
                log.error("同步外部小程序展会信息失败，请手动同步处理！{}", exhibition);
            }else {
                log.info("同步外部小程序展会信息成功,{},{}", exhibition,miceHttp);
            }
        } catch (Exception e) {
            log.error("同步外部小程序展会信息失败，请手动同步处理！{},{}", exhibition, e);
        }
    }

    @Override
    public void updateExhibitionState(List<Long> asList) {
        for (Long exhibitionId : asList) {
            if(Objects.nonNull(exhibitionId)){
                Exhibition exhibition = getById(exhibitionId);
                if(Objects.nonNull(exhibition)){
                    Exhibition updateEntity = new Exhibition();
                    updateEntity.setId(exhibitionId);
                    // 查询报价书
                    QuotationDTO quotationDTO = new QuotationDTO();
                    quotationDTO.setExhibitionId(exhibition.getId());
                    List<Quotation> quotationList = quotationService.listQuotation(quotationDTO);
                    // 查询商机
                    List<ExhibitionBusinessOpportunity> exhibitionBusinessOpportunities = exhibitionBusinessOpportunityService.list(new QueryWrapper<ExhibitionBusinessOpportunity>().lambda()
                            .eq(ExhibitionBusinessOpportunity::getIsDeleted, BusinessConstant.NO)
                            .eq(ExhibitionBusinessOpportunity::getExhibitionId, exhibitionId));
                    if (CollectionUtils.isNotEmpty(quotationList)) {
                        // 报价确认
                        updateEntity.setState(ExhibitionStateEnum.STATE_THREE);
                    } else if (CollectionUtils.isNotEmpty(exhibitionBusinessOpportunities)) {
                        // 销售商机
                        updateEntity.setState(ExhibitionStateEnum.STATE_TWO);
                    } else {
                        // 无状态
                        updateEntity.setState(ExhibitionStateEnum.STATE_ONE);
                    }
                    updateById(updateEntity);
                }
            }
        }
    }

    @Override
    protected R<Boolean> handlerSave(Exhibition model) {
        model.setProjectId(ContextUtil.getProjectId());
        model.setSubsystemId(ContextUtil.getSubSystemId());
        model.setTenantId(ContextUtil.getTenantId());
        //雪花ID
        return R.successDef();
    }

}
